package org.itboys.mysql.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ClassUtils;

/**
 * 对象工具类
 */
public class ObjectUtils {

	/**
	 * 获得类的所有属性
	 * @param clazz
	 * @return
	 */
	public static List<Field> getAllField(Class<?> clazz) {
		List<Field> list = new ArrayList<Field>();
		for (Field field : clazz.getDeclaredFields()) {
			list.add(field);
		}
		Class<?> _clazz = clazz.getSuperclass();
		while(_clazz != null) {
			list.addAll(getAllField(_clazz));
			_clazz = _clazz.getSuperclass();
		}
		return list;
	}

	/**
	 * 获得类的所有标注了指定的atClass类型注解的属性
	 * @param clazz
	 * @param atClass
	 * @return
	 */
	public static List<Field> getFieldsByAnnotation(
			Class<?> clazz, Class<? extends Annotation> atClass) {
		List<Field> list = getAllField(clazz);
		List<Field> ret = new ArrayList<Field>();
		for (Field field : list) {
			if(field.getAnnotation(atClass) != null) {
				ret.add(field);
			}
		}
		return ret;
	}

	/**
	 * 获得clazz指定类型的初始值（原始数据类型返回“0”值，引用类型返回null）
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getInitialValue(Class<T> clazz) {
		if(clazz == boolean.class) {
			return (T)Boolean.valueOf(false);
		}
		if(clazz == char.class) {
			return (T)Character.valueOf('\0');
		}
		if(clazz.isPrimitive()) {
			try {
				return (T)ClassUtils.primitiveToWrapper(clazz).getConstructor(String.class).newInstance("0");
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return null;
	}

	/**
	 * 序列化对象
	 * @param obj
	 * @return
	 */
	public static byte[] serialize(Object obj) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(obj);
		    oos.flush();
		    oos.close();
		    return baos.toByteArray();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	    
	}

	/**
	 * 反序列化方法
	 * @param bytes
	 * @return
	 */
	public static Object unSerialize(byte[] bytes) {
		Object obj = null;
		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);	
		try {
			ObjectInputStream ois = new ObjectInputStream(bais);
			obj = ois.readObject();
			return obj;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}		 
	}

	/**
	 * 对象的深层复制，obj的实例类型必须实现序列化接口，否则将抛出异常
	 * @param <T>
	 * @param obj
	 * @return
	 */
	public static <T> T clone(T obj) {
		@SuppressWarnings("unchecked")
		T ret = (T) unSerialize(serialize(obj));
		return ret; 
	}

	/**
	 * 从InputStream中读取对象
	 * @param input    输入流
	 * @return Object  读取的对象
	 * @throws IOException
	 */
	public static Object read(InputStream input) throws IOException {
		List<byte[]> byteList = new ArrayList<byte[]>();
		List<Integer> countList = new ArrayList<Integer>();
		byte[] bytes = new byte[1024];
		int count = 0;
		int total = 0;
		while ((count=input.read(bytes)) != -1) {
			byteList.add(bytes);
			bytes = new byte[bytes.length];
			countList.add(count);
			total += count;
		}
		byte[] result = new byte[total];
		int k = 0;
		for (int i = 0; i < byteList.size(); i++) {
			for (int j = 0; j < countList.get(i); j++) {
				result[k++] = byteList.get(i)[j];
			}
		}
		return unSerialize(result);
	}

	/**
	 * 向OutputStream中写入对象
	 * 
	 * @param output  输出流
	 * @param obj     写入的对象
	 * @throws IOException
	 */
	public static void write(OutputStream output, Object obj) throws IOException {
		output.write(serialize(obj));
		output.flush();
	}

}
